package com.hh.service.impl;

import com.hh.controller.UserController;
import com.hh.mapper.PostMapper;
import com.hh.mapper.PostReplyMapper;
import com.hh.mapper.UserBarRelevancyMapper;
import com.hh.mapper.UserMapper;
import com.hh.pojo.MessageModel;
import com.hh.pojo.User;
import com.hh.service.UserService;
import com.hh.utils.FileTool;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private PostMapper postMapper;

    @Autowired
    private UserBarRelevancyMapper ubrMapper;

    @Autowired
    private PostReplyMapper postReplyMapper;

    @Override
    public MessageModel judgeUserExist(String uname) {
        MessageModel messageModel = new MessageModel(200, "用户名可用。");

        try {
            if (userMapper.getUserByUname(uname) != null){
                messageModel.setResult_code(305);
                messageModel.setMsg("抱歉，该用户名已被使用.");
            }
        }catch (Exception e){
            messageModel.setResult_code(303);
            messageModel.setMsg("数据库查询发生异常!");
            e.printStackTrace();
        }
        return messageModel;
    }

    /*更新一个用户*/
    @Override
    public MessageModel updateUser(String uname, String nickName, MultipartFile headImg, String motto, String birthday,
                                   String[] area, String intro, String originalHeadImg, String path) {
        MessageModel rs = new MessageModel(200, "修改成功！");
        int i;  /*文件名 小数点位置*/
        String fileType;  /*文件类型 包括.*/
        String saveName;  /*文件保存名*/
        String separator = File.separator; //定义分隔符
        Map<String, Object> map = new HashMap<>();

        if (headImg.getSize() != 0){ /*用户重新选择了头像文件*/
            System.out.println("用户重新选择了头像文件");
            if (!originalHeadImg.equals("default.png")){ /*如果原头像不是默认头像则将原头像删除*/
               if ( FileTool.deleteFile(path + separator + originalHeadImg) == 0){
                   rs.setResult_code(409);
                   rs.setMsg("原头像删除失败！信息修改失败！");
                   System.out.println("修改了头像文件，且原头像不为默认头像，删除原头像失败！");
                   return rs; //不更新数据库  直接返回
               }
            }

            /*将新头像写入保存*/
            i = Objects.requireNonNull(headImg.getOriginalFilename()).lastIndexOf('.');
            fileType = headImg.getOriginalFilename().substring(i);  /*包括.*/
            fileType = fileType.toLowerCase(); //一律转小写
            saveName = uname + fileType;
            try {
                headImg.transferTo(new File(path + separator + saveName));
                map.put("headImg", saveName);
            } catch (IOException e) {
                rs.setResult_code(408);
                rs.setMsg("新头像写入失败！信息修改失败！");
                e.printStackTrace();
                System.out.println("新头像写入失败！信息修改失败！");
                return rs;  //不更新数据库  直接返回
            }
        }

        /*更新数据库记录*/
        try {
            map.put("uname", uname);
            map.put("nickName", nickName);
            map.put("motto", motto);
            map.put("birthday", birthday);
            map.put("area", area);
            map.put("intro", intro);
            if (userMapper.updateUser(map) < 1){
                rs.setMsg("数据库记录更新失败！信息修改失败！");
                rs.setResult_code(302);
            }
        }catch (Exception e){
            rs.setResult_code(303);
            rs.setMsg("数据更新发生异常!信息修改失败！");
            e.printStackTrace();
        }
        return rs;
    }

    // sensitive false -- 获取全部字段   true -- 不获取敏感数据
    public Map<String, Object> getUserByName(String uname, boolean sensitive) {
        MessageModel messageModel = new MessageModel(200, "user获取成功!");
        Map<String, Object> map = new HashMap<>();

        try {
            User user = userMapper.getUserByUname(uname);
            user.initArea();

            // 敏感处理
            if (sensitive){
                user.setUpwd(null);
            }

            map.put("user", user);
        }catch (Exception e){
            e.printStackTrace();
            messageModel.setResult_code(303);
            messageModel.setMsg("数据库查询用户发生异常！");
        }

        map.put("rs", messageModel);
        return map;
    }

    @Override
    public Map<String, Object> getUserByName(String uname) {
        return getUserByName(uname, false);
    }


    @Override
    public Map<String, Object> getSPUserByName(String uname) {
        return getUserByName(uname, true);
    }

    @Override
    public Map<String, Object> login(String uname, String upwd) {
        Map<String, String> map = new HashMap<>();
        Map<String, Object> rsMap = new HashMap<>();
        MessageModel loginRs = new MessageModel(200, "登录成功！");
        map.put("uname", uname);
        map.put("upwd", upwd);

        User user = userMapper.getUser(map);
        try {
            if (user == null){
                loginRs.setResult_code(310);
                loginRs.setMsg("用户名或密码错误！");
            }else {  /*用户名密码成功匹配*/
                /*由于mybatis  select 好像无法直接把数据库中的两个字段 赋值给一个数组，只好在user类中新建两个属性，对应那两个字段，
                * 为了方便，用直接用那两个字段来初始化那个area字符串数组了。
                * */
//                user.setArea(new String[]{user.getAreaProvince(), user.getAreaCity()});
                user.initArea();
                rsMap.put("user", user);
            }
        }catch (Exception e){
            loginRs.setResult_code(303);
            loginRs.setMsg("数据库查询发生异常!");
            e.printStackTrace();
        }

        rsMap.put("rsMessageModel", loginRs);
        return rsMap;
    }

    /*检验是否已登录   检验是否具有管理员权限*/
    @Override
    public MessageModel checkUserRight(HttpServletRequest request) {
        User user = UserController.getCurrentUser(request);
        MessageModel rs = new MessageModel(200, "已作为管理员登录~");

        if (user == null){ //从session 中取user 变量，没有则表示没登录
            rs.setResult_code(605);
            rs.setMsg("当前未登录！请先登录！！");
        }else {
            if (!isAdmin(user)){
                rs.setResult_code(609);
                rs.setMsg("抱歉，权限不足，请先获取管理员权限~！");
            }
        }

        return rs;
    }

    @Override
    public Boolean isAdmin(User user) {
        //如果user为空  默认表示不是管理员 返回false
        if (user == null){
            return false;
        }

        return "admin".equals(user.getRole());
    }

    @Override
    public Map<String, Object> getUserCountInfo(String uname) {
        MessageModel messageModel = new MessageModel(200, "用户数量信息获取成功!");
        Map<String, Object> map = new HashMap<>();

        try {
            User user = userMapper.getUserByUname(uname);
            // 判断用户是否存在
            if (user == null){
                messageModel.setResult_code(307);
                messageModel.setMsg("用户不存在！ 数量信息获取失败！");
            }else {
                // 调用三个mapper的对应方法，获取用户的item数
                map.put("postCount", postMapper.getPostCountByUser(uname));
                map.put("prCount", postReplyMapper.getPostReplyCountByUser(uname));
                map.put("barCount", ubrMapper.getBarCountByUser(uname));
            }
        }catch (Exception e){
            e.printStackTrace();
            messageModel.setResult_code(303);
            messageModel.setMsg("数据库查询用户数量信息发生异常！");
        }

        map.put("rs", messageModel);
        return map;
    }

    @Override
    public MessageModel insertUser(String uname, String upwd, String nickName, MultipartFile headImg, String motto,
                          String email, String birthday, String[] area, String intro, String path) {
        /*path 表示文件上传保存的路径  由controller request.getServletContext().getRealPath() 获得  到userAvatar目录*/
        User userToInsert = new User();
        MessageModel rs = new MessageModel();
        File filePath = new File(path);  //文件上传路径（不包括文件名）
        String saveName;  /*文件保存名*/
        String separator = File.separator; //定义分隔符
        int i;  /*文件名 小数点位置*/
        String fileType;  /*文件类型 包括.*/

        /*简单注册时的 数据初始化*/
        /*因为简单注册时，前端只传来用户名和密码，其他值都为null，而dao层中sql里判断的是为不为“”，（数组则判断长度是否为0）
            所以 没去改dao层，在这里进行一些空的初始化
        * */
        if (nickName == null){
            nickName = "";
        }
        if (motto == null){
            motto = "";
        }
        if (email == null){
            email = "";
        }
        if (birthday == null){
            birthday = "";
        }
        if (area == null){
            area = new String[]{};
        }
        if (intro == null){
            intro = "";
        }
        userToInsert.setUname(uname);
        userToInsert.setUpwd(upwd);
        userToInsert.setNickName(nickName);
        if (headImg != null){
            userToInsert.setHeadImg(headImg.getOriginalFilename());
        }else { //简单注册时 传来的headImg 为null  这里设置为空字符串“”  配合dao层中的判断
            userToInsert.setHeadImg("");
        }
        userToInsert.setMotto(motto);
        userToInsert.setEmail(email);
        userToInsert.setBirthday(birthday);
        userToInsert.setArea(area);
        userToInsert.setIntro(intro);
        rs.setResult_code(200);  /*默认成功*/
        rs.setMsg("注册成功！");

        try {
            if (headImg != null){
                // 如果上传了文件的话， 将头像以用户名（id） 保存     将文件保存到服务器
                if (headImg.getSize() != 0){
                    i = Objects.requireNonNull(headImg.getOriginalFilename()).lastIndexOf('.');
                    fileType = headImg.getOriginalFilename().substring(i);  /*包括.*/
                    fileType = fileType.toLowerCase(); //一律转小写
                    saveName = uname + fileType;

                    userToInsert.setHeadImg(saveName);
                    headImg.transferTo(new File(filePath + separator + saveName));
                }
            }
            //将记录写入数据库
            if (userMapper.insertUser(userToInsert) < 1){
                rs.setResult_code(300);
                rs.setMsg("数据库插入失败！");
            }
        }catch (IOException e){
            rs.setResult_code(408);
            rs.setMsg("文件写入发生异常。");
            e.printStackTrace();
        }
        catch (Exception e){
            rs.setResult_code(303);
            rs.setMsg("数据库插入发生异常。");
            e.printStackTrace();
        }
        return rs;
    }

}
